#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include "./include/ipc.h"

#define  PRODUCT_NUM  30   // 产品数量
#define  CMD_SIZE     100  // 输入命令的字符数

int scanline(char *buf, int n);   // 从控制台读取一行

int main(int argc, char *argv[])
{
    //
    // 申请共享内存
    //
    int shmid = get_shm(SHM_KEY);
    //
    // 绑定共享内存到进程地址空间
    //
    shmd_t* shmd_ptr = (shmd_t*)attach_shm(shmid);
    init_shm(shmd_ptr, PRODUCT_NUM);
    show_shm(printf, shmd_ptr);

    //
    // 申请信号量
    //
    int metuxid = get_sem(MUTEX_KEY);
    int fullid = get_sem(FULL_KEY);
    int emptyid = get_sem(EMPTY_KEY);

    //
    // 初始化信号量
    //
    init_sem(metuxid, 1);
    init_sem(fullid, 0);
    init_sem(emptyid, BUFFER_SIZE);

    //
    // 提示创建生产者进程
    //
    system("gnome-terminal");
    printf("\n  shm and sem init success!\n");
    printf("  please start producer at the new open terminal!\n");

    // 
    // 读取控制命令
    //
    char cmd[CMD_SIZE];
    int speed;
    while( 1 ) {
        printf("\n[input cmd]#: ");
        if(-1 != scanline((char *)cmd, CMD_SIZE)) {
            if(0 == strcmp(cmd, "exit")) {
                //
                // 输入 exit 退出
                //
                sem_pv(metuxid, -1);
                    shmd_ptr->p_speed = 0;  // 给生产者发送停止生产命令
                sem_pv(metuxid, 1);
                break;

            } else if(0 == strncmp(cmd, "p -s", 4)) {
                //
                // 控制生产者生产速度
                //
                speed = atoi( (const char *)(cmd + 4) );
                if(speed > 0) {
                    sem_pv(metuxid, -1);
                        shmd_ptr->p_speed = speed;
                    sem_pv(metuxid, 1);
                }

            } else if(0 == strncmp(cmd, "c -s", 4)) {
                //
                // 控制消费者消费速度
                //
                speed = atoi( (const char *)(cmd + 4) );
                if(speed > 0) {
                    sem_pv(metuxid, -1);
                        shmd_ptr->c_speed = speed;
                    sem_pv(metuxid, 1);
                }
                
            } else if(0 == strcmp(cmd, "show shm")) {
                sem_pv(metuxid, -1);
                    show_shm(printf, shmd_ptr);
                sem_pv(metuxid, 1);

            } else {
                printf("  unkown command, please check and input again!\n");
            }
        }
    }

    //
    // 等待生产者和消费者执行结束
    //
    while( 1 ) {
        if(-1 == shmd_ptr->p && -1 == shmd_ptr->c) {
            break;
        }
    }
    
    //
    // 释放共享内存和信号量资源
    //
    printf("  manager begin free shm and sem...\n");
    free_shm(shmd_ptr, shmid);
    free_sem(metuxid);
    free_sem(fullid);
    free_sem(emptyid);
    printf("  free over, bye bye!!!\n\n");

    return 0;
}

/*
 * 从控制台读取一行
 */
int scanline(char *buf, int size)
{
    assert(buf);
    char ch;
    scanf("%c", &ch);
    int i;
    for(i = 0; '\n' != ch; i++) {
        if( i >= size ) {
            printf("  error: cmd too long, input_size can't above %d\n", size);
            return -1;
        }
        buf[i] = ch;
        scanf("%c", &ch);
    }
    buf[i]='\0';
    return 0;
}
